/* 
 * StikiWeb Wiki - a Wiki for Hierarchical Organizations
 * $Id: AttachFileAction.java,v 1.6 2004/09/18 22:24:50 biglee Exp $
 * 
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the StikiWeb Wiki.
 *
 * The Initial Developer of the Original Code is Lee Haslup (biglee@haslups.com).
 * Portions created by the Initial Developer are Copyright (C) 2004
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** 
 */
package org.stikiweb.struts;

import java.io.InputStream;
import java.io.InputStreamReader;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;
import org.stikiweb.contentMagnager.AttachmentManager;
import org.stikiweb.contentMagnager.PageInfoNode;
import org.stikiweb.contentMagnager.PageManager;
import org.stikiweb.contentMagnager.PermissionManager;

/**
 * @author Allen L (BigLee) Haslup
 *
 */
public class AttachFileAction extends StikiAction {

	/* (non-Javadoc)
	 * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	public ActionForward execute(
		ActionMapping mapping,
		ActionForm form,
		HttpServletRequest req,
		HttpServletResponse resp)
		throws Exception {
		setup(req);
		HttpSession session = req.getSession();
		AttachmentBean ab = (AttachmentBean) form;

		// if there is no input we don't know to what page to attach so we fail.
		if (ab == null || ab.getName() == null) {
			// no point redirecting to the jsp -- name is a hidden field.
			return mapping.findForward("failure");
		}

		// if the user hit cancel, just go display the current page.
		String returnTo = (String) session.getAttribute("currentPage");
		if(returnTo==null) {
			returnTo = "Main";
		} 
		if (req.getParameter("cancel") != null) {
			return new ActionForward("/viewPage.do?name=" + returnTo);
		}

		try {
			PageManager pm = PageManager.solo();
			String name = ab.getName();

			// if the page doesn't exist  we fail.
			if (!pm.pageExists(name)) {
				// no point redirecting to the jsp -- name is a hidden field.
				return mapping.findForward("failure");
			}

			// if we don't have the permission to perform the operation...
			PermissionManager permM = PermissionManager.solo();
			String userName = getUserName(req);
			int permLevel = permM.userPermLevelForPage(userName, name);
			

			if (permLevel < PermissionManager.ATTACH){
				// ... and we are logged in, fail.
				if (isLoggedIn(req)) {
					return mapping.findForward("failure");
				}
				// if we are not logged in, try logging in and see if that helps.
				else {
					return goLoginFirst("attach", "", name, req);
				}
			}

			// the limit on the size of this upload is either the max storage per attachment
			// or the available space, whichever is more restrictive.
			long maxSize = permM.maxStoragePerAttachFor(name)*100000;
			long availStorage = PageInfoNode.availableStorage(name);
			long limitRightNow = maxSize < availStorage ? maxSize : availStorage;
			
			// if user pressed the "attach" button			
			if(req.getParameter("attach")!=null) {
				
				// make sure a file was uuploaded
				FormFile uploaded = ab.getTheAttachment();
				if(uploaded==null || uploaded.getFileName().length()==0) {
					ActionErrors errors = new ActionErrors();
					errors.add(ActionErrors.GLOBAL_MESSAGE,new ActionError("error.upload.fileMissing"));
					saveErrors(req,errors);
					return new ActionForward(mapping.getInput());
				}
				
				// make sure it is not too big.
				if(uploaded.getFileSize()>limitRightNow) {
					ActionErrors errors = new ActionErrors();
					errors.add(ActionErrors.GLOBAL_MESSAGE,new ActionError("error.upload.fileTooBig"));
					saveErrors(req,errors);
					ab.setMaxSize(Long.toString(limitRightNow));
					return new ActionForward(mapping.getInput());
				}
				
				// attaching a .wiki page is the same as creating a child page.
				boolean isWiki = uploaded.getFileName().endsWith(".wiki");
				
				if(isWiki) {
					// re-examine permission in light of the fact that this is a child page
					if ( permLevel < PermissionManager.EXTEND){
						// ... and we are logged in, fail.
						if (isLoggedIn(req)) {
							return mapping.findForward("failure");
						}
						// if we are not logged in, try logging in and see if that helps.
						else {
							return goLoginFirst("attach", "", name, req);
						}
					}
					// save the child page...
					String childName = name+"."+uploaded.getFileName();
					// Strip off the .wiki from the name
					childName = childName.substring(0,childName.length()-5);
					// copy into a string buffer
					StringBuffer sb = new StringBuffer();
					InputStream is = uploaded.getInputStream();
					InputStreamReader ir = new InputStreamReader(is);
					int c = ir.read();
					while(c>=0) {
						sb.append((char)c);
						c = ir.read();
					}
					// and save.
					PageManager.solo().savePage(childName,sb.toString());
				
				}
				else {
					// attach the file...
					AttachmentManager.solo().attach(name,uploaded);
				}
				return new ActionForward("/viewPage.do?name=" + returnTo);
			}
			
			// if there is no file attached to the bean then go get input
			if(ab.theAttachment==null) {
				ab.setMaxSize(Long.toString(limitRightNow));
			}
			
			//ab.theAttachment.getFileSize()
			return new ActionForward(mapping.getInput());
		} catch (Exception e) {
			return mapping.findForward("failure");
		}
	}

}
